package com.gitee.wsl.android.ui.ext.type

import android.graphics.*
import android.graphics.drawable.Drawable
import android.os.Build
import android.text.Layout
import android.text.StaticLayout
import android.text.TextPaint
import androidx.compose.ui.geometry.Size
import androidx.core.graphics.withSave
import com.gitee.wsl.android.ui.base.BezierLine
import com.gitee.wsl.android.ui.ext.type.CanvasExt.getPaintFontHeight
import com.gitee.wsl.common.ui.base.getSizeOfRotatedRectangleByRadians
import com.gitee.wsl.mathematics.geometry.d2.base.Direction
import com.gitee.wsl.common.ui.draw.type.DrawStyle
import com.gitee.wsl.common.ui.draw.type.FillType
import com.gitee.wsl.common.ui.draw.type.LineSpacingStyle
import com.gitee.wsl.common.ui.draw.type.TriangleStyle
import com.gitee.wsl.math.degreesToRadians
import com.gitee.wsl.mathematics.geometry.shape.Rectangle
import kotlin.math.ceil
import kotlin.math.floor
import kotlin.math.max
import kotlin.math.tan

object CanvasExt {

    /**
     * 得到单个字的高度
     * @param paint 画笔
     * @return 高度
     */
    fun getPaintFontHeight(paint: Paint): Float {
        val fm = paint.fontMetrics
        return ceil(fm.descent - fm.ascent)
    }

    /**
     * 得到字符串的宽度
     * @param paint 画笔
     * @param str 字符串
     * @return 宽度
     */
    fun getTextWidth(paint: Paint, str: String): Float {
        return if (str.isEmpty()) 0.0f else paint.measureText(str, 0, str.length)
        //float width = Math.abs(paint.measureText(str, 0, str.length()));
    }

    /**
     * 用于计算文字的竖直累加高度
     * @param paint 画笔
     * @param str   字符串
     * @return 高度
     */
    fun calcTextHeight(paint: Paint, str: String): Float {
        return if (str.isEmpty()) 0f else getPaintFontHeight(paint) * str.length
    }

    /**
     * Returns the background rect for the highlighted text.
     * @param x : X point.
     * @param y: Y point.
     * @param text: Text to be drawn inside the background.
     * @param paint: Background paint.
     */
    fun getTextBackgroundRect(
        x: Float,
        y: Float,
        text: String,
        paint: TextPaint
    ): RectF {
        val fontMetrics = paint.fontMetrics
        val textLength = paint.measureText(text)
        return RectF(
            x - (textLength / 2),
            y + fontMetrics.top,
            x + (textLength / 2),
            y + fontMetrics.bottom
        )
    }

}


/**
 * Returns the height of a single line of text.
 */
 val Paint.lineHeight: Float
    get() = fontMetrics.bottom - fontMetrics.top + fontMetrics.leading


/**
 * Returns the height of text.
 */
 val Paint.textHeight: Float
    get() = CanvasExt.getPaintFontHeight(this)


/**
 * Returns the width of the provided text.
 */
fun Paint.textWidth(text: String): Float =CanvasExt.getTextWidth(this,text)


/**
 * 绘制旋转了指定角度的文字
 * @param text    文字
 * @param x        X坐标
 * @param y        y坐标
 * @param paint    画笔
 * @param angle 角度
 */
fun Canvas.drawRotateText(
    text: String,
    x: Float, y: Float, angle: Float,
    paint: Paint
) {
    if ("" === text || text.isEmpty()) return

    if (angle != 0f) {
        rotate(angle, x, y)
        //canvas.drawText(text, x, y, paint);
        drawMultilineText(paint, text, x, y)
        rotate(-1 * angle, x, y)
    } else {
        //canvas.drawText(text, x, y, paint);
        drawMultilineText(paint, text, x, y)
    }
}

//绘制有换行的文本
fun Canvas.drawMultilineText(paint: Paint, text: String, x: Float, y1: Float): Float {
    var y = y1
    if (text.isNotEmpty()) {
        if (text.indexOf("\n") > 0) {
            val height = getPaintFontHeight(paint)
            val arr = text.split("\n").toTypedArray()
            for (i in arr.indices) {
                drawText(arr[i], x, y, paint)
                y += height
            }
        } else {
            drawText(text, x, y, paint)
        }
    }
    return y
}

fun Canvas.drawMultilineText(
    textLayout: StaticLayout,
    x: Float, y: Float,
    paint: TextPaint,
    anchor: PointF,
    angleDegrees: Float,
    paddingLeft:Float = 0f
) {
    var drawOffsetX = 0f
    var drawOffsetY = 0f
    val drawHeight: Float
    val lineHeight = paint.lineHeight
    val drawWidth: Float = textLayout.width.toFloat()
    drawHeight = textLayout.lineCount * lineHeight

    // Android sometimes has pre-padding
    drawOffsetX -= paddingLeft

    // Android does not snap the bounds to line boundaries,
    //  and draws from bottom to top.
    // And we want to normalize it.
    drawOffsetY += drawHeight

    // To have a consistent point of reference, we always draw left-aligned
    val originalTextAlign = paint.textAlign
    paint.textAlign = Paint.Align.LEFT
    if (angleDegrees != 0f) {

        // Move the text drawing rect in a way that it always rotates around its center
        drawOffsetX -= drawWidth * 0.5f
        drawOffsetY -= drawHeight * 0.5f
        var translateX = x
        var translateY = y

        // Move the "outer" rect relative to the anchor, assuming its centered
        if (anchor.x != 0.5f || anchor.y != 0.5f) {
            val rotatedSize: Size = Size( drawWidth, drawHeight).getSizeOfRotatedRectangleByRadians(angleDegrees.degreesToRadians())
            translateX -= rotatedSize.width * (anchor.x - 0.5f)
            translateY -= rotatedSize.height * (anchor.y - 0.5f)
        }

        withSave {
            translate(translateX, translateY)
            rotate(angleDegrees)
            translate(drawOffsetX, drawOffsetY)
            textLayout.draw(this)
        }
    } else {
        if (anchor.x != 0f || anchor.y != 0f) {
            drawOffsetX -= drawWidth * anchor.x
            drawOffsetY -= drawHeight * anchor.y
        }
        drawOffsetX += x
        drawOffsetY += y
        withSave {
            translate(drawOffsetX, drawOffsetY)
            textLayout.draw(this)
        }
    }
    paint.textAlign = originalTextAlign
}

fun Canvas.drawMultilineText(
    text: String,
    x: Float, y: Float,
    paint: TextPaint,
    constrainedToSize: Size,
    anchor: PointF, angleDegrees: Float
) {
    val builder=StaticLayout.Builder.obtain(text,0,text.length,paint, max(ceil(constrainedToSize.width), 1.0f).toInt())
    builder.setAlignment(Layout.Alignment.ALIGN_NORMAL)
        .setIncludePad(false)
        .setLineSpacing(0f, 1f)
    drawMultilineText(builder.build(), x, y, paint, anchor, angleDegrees)
}

/**
 * 绘制等腰三角形
 * @param baseLine        底线长度
 * @param baseLnCentX    底线中心点X坐标
 * @param baseLnCentY    底线中心点Y坐标
 * @param direction        三角形方向
 * @param style            填充风格
 * @param canvas        画布
 * @param paint            画笔
 */
fun Canvas.drawTriangle(
    baseLine: Float,
    baseLnCentX: Float,
    baseLnCentY: Float,
    direction: Direction = Direction.RIGHT,
    style: TriangleStyle = TriangleStyle.FILL,
    paint: Paint,
    drawStyle: DrawStyle = DrawStyle.DEFAULT
) {
    // 计算偏移量
    val offset = (baseLine / 2 * tan(60 * Math.PI / 180)).toFloat()
    when (direction) {
        Direction.UP -> {
            drawTriangle(
                baseLnCentX - baseLine / 2, baseLnCentY,
            baseLnCentX + baseLine / 2, baseLnCentY,
                baseLnCentX, baseLnCentY - offset,
                paint,style)
        }
        Direction.DOWN -> {
            drawTriangle(
                baseLnCentX - baseLine / 2, baseLnCentY,
            baseLnCentX + baseLine / 2, baseLnCentY,
                baseLnCentX, baseLnCentY + offset,
                paint,style)
        }
        Direction.LEFT -> {
            drawTriangle(
                baseLnCentX, baseLnCentY - baseLine / 2,
                baseLnCentX, baseLnCentY + baseLine / 2,
                baseLnCentX - offset, baseLnCentY,
                paint,style)
        }
        Direction.RIGHT -> {
            drawTriangle(
            baseLnCentX, baseLnCentY - baseLine / 2,
            baseLnCentX, baseLnCentY + baseLine / 2,
            baseLnCentX + offset, baseLnCentY,
            paint,style)
        }
    }

}

fun Canvas.drawTriangle(
                 p0x: Float, p0y: Float,
                 p1x: Float, p1y: Float,
                 p2x: Float, p2y: Float,
                 paint: Paint,
                 style: TriangleStyle = TriangleStyle.FILL
) {
    val path = Path().apply {
        moveTo(p0x, p0y)
        lineTo(p1x, p1y)
        lineTo(p2x, p2y)
        close()
    }
    val oldStyle=paint.style
    when (style) {
        TriangleStyle.OUTLINE -> paint.style = Paint.Style.STROKE
        TriangleStyle.FILL -> paint.style = Paint.Style.FILL
    }
    drawPath(path, paint)
    paint.style=oldStyle
}

fun Canvas.draw2Triangle(
              startPos: Float, endPos: Float,
              topPos: Float, bottomPos: Float,
              paint: Paint) {
    val divide = topPos + (bottomPos - topPos) * 0.7f
    drawRect(startPos, topPos, endPos, divide, paint)
    drawTriangle(
        startPos, divide,
        startPos + bottomPos - divide, divide,
        startPos, bottomPos,
        paint)
    drawTriangle(
        endPos, divide,
        endPos - bottomPos + divide, divide,
        endPos, bottomPos,
        paint)
}

//下次应当做的:虚实线 比例的灵活定制,线的阴影渲染
fun Canvas.drawLine(
    style: LineSpacingStyle,
    startX: Float, startY: Float,
    stopX: Float, stopY: Float,
    paint: Paint,
    drawStyle: DrawStyle = DrawStyle.DEFAULT
) {
    lineStyle(style,paint){
        drawLine(startX, startY, stopX, stopY, it)
    }
}

fun Canvas.lineStyle(style: LineSpacingStyle, paint: Paint, block:Canvas.(Paint)->Unit){
     val oldEffect = paint.pathEffect
     paint.pathEffect =  when (style) {
         LineSpacingStyle.Solid -> null
         LineSpacingStyle.Dot -> LineExt.dotLineStyle
         LineSpacingStyle.Dash -> LineExt.dashLineStyle         //虚实线
         else -> null
     }
     block(paint)
     paint.pathEffect = oldEffect
 }


/**
 * 二次
 */
fun Canvas.drawQuadraticCurve(
    startX: Float, startY: Float,
    cp1X: Float, cp1Y: Float,
    endX: Float, endY: Float,
    paint: Paint,
    style: LineSpacingStyle = LineSpacingStyle.Solid
){
    val path=Path()
    path.moveTo(startX,startY)
    path.quadTo(cp1X,cp1Y,endX,endY)
    lineStyle(style,paint) {
        drawPath(path, it)
    }
}

/**
 * 三次
 */
fun Canvas.drawBezierCurve(
    startX: Float, startY: Float,
    cp1X: Float, cp1Y: Float,
    cp2X: Float, cp2Y: Float,
    endX: Float, endY: Float,
    paint: Paint,
    style: LineSpacingStyle = LineSpacingStyle.Solid
){
    val path = Path()
    path.moveTo(startX,startY)
    path.cubicTo(cp1X,cp1Y,cp2X,cp2Y,endX,endY)
    lineStyle(style,paint){
        drawPath(path,it)
    }
}

/**
 *  使用控制点
 */
fun Canvas.drawBezierCurve(
    startX: Float, startY: Float,
    endX: Float, endY: Float,
    vararg points:PointF,
    paint: Paint,
    style: LineSpacingStyle = LineSpacingStyle.Solid
) {
    when(points.size){
        0->drawLine(startX,startY,endX,endY,paint)
        1->drawQuadraticCurve(startX,startY,points[0].x,points[0].y,endX, endY, paint,style)
        2->drawBezierCurve(startX,startY,points[0].x,points[0].y,points[1].x,points[1].y,endX, endY, paint,style)
        else->{
            val path = BezierLine.buildBezierLine(startX, startY, endX, endY, *points)
            lineStyle(style,paint){
                drawPath(path,it)
            }
        }
    }
}


/**
 *  使用节点
 */
fun Canvas.drawBezierCurveUseKnots(
    knots:List<PointF>,
    paint: Paint,
    style: LineSpacingStyle = LineSpacingStyle.Solid
){
    val path = BezierLine.buildBezierLineUseKnots(knots)
    lineStyle(style,paint){
        drawPath(path,it)
    }
}


/**
 * A more customizable drawRoundRect function
 */
fun Canvas.drawRoundRect(
    left: Float,
    top: Float,
    right: Float,
    bottom: Float,
    topLeft: Float,
    topRight: Float,
    bottomLeft: Float,
    bottomRight: Float,
    paint: Paint
) {
    val maxRound = arrayOf(topLeft, topRight, bottomLeft, bottomRight).maxOf { it }
    val width = right - left
    val height = bottom - top

    // draw first/global rect
    drawRoundRect(left, top, right, bottom, maxRound, maxRound, paint)

    // top left border
    if (topLeft == 0f) {
        drawRect(left, top, left + width / 2, top + height / 2, paint)
    } else {
        drawRoundRect(left, top, left + width / 2, top + height / 2, topLeft, topLeft, paint)
    }

    // top right border
    if (topRight == 0f) {
        drawRect(right - width / 2, top, right, top + height / 2, paint)
    } else {
        drawRoundRect(right - width / 2, top, right, top + height / 2, topRight, topRight, paint)
    }

    // bottom left border
    if (bottomLeft == 0f) {
        drawRect(left, bottom - height / 2, left + width / 2, bottom, paint)
    } else {
        drawRoundRect(
            left,
            bottom - height / 2,
            left + width / 2,
            bottom,
            bottomLeft,
            bottomLeft,
            paint
        )
    }

    // bottom right border
    if (bottomRight == 0f) {
        drawRect(right - width / 2, bottom - height / 2, right, bottom, paint)
    } else {
        drawRoundRect(
            right - width / 2,
            bottom - height / 2,
            right,
            bottom,
            bottomRight,
            bottomRight,
            paint
        )
    }

}

/**
 * A more customizable drawRoundRect function
 */
fun Canvas.drawRoundRect(
    rect: RectF,
    topLeft: Float,
    topRight: Float,
    bottomLeft: Float,
    bottomRight: Float,
    paint: Paint
) {
    drawRoundRect(
        rect.left,
        rect.top,
        rect.right,
        rect.bottom,
        topLeft,
        topRight,
        bottomLeft,
        bottomRight,
        paint
    )
}


/**
 * 绘制图中显示所占比例 的扇区
 * @param paintArc    画笔
 * @param cirX    x坐标
 * @param cirY    y坐标
 * @param radius    半径
 * @param startAngle    偏移角度
 * @param sweepAngle    当前角度
 * @throws Exception    例外
 */
fun Canvas.drawPercentArc(
    paintArc: Paint,
    cirX: Float,
    cirY: Float,
    radius: Float,
    startAngle: Float,
    sweepAngle: Float,
    useCenter: Boolean,
    drawStyle: DrawStyle = DrawStyle.DEFAULT
) {
    val mRectF = RectF()
        mRectF.left = cirX - radius
        mRectF.top = cirY - radius
        mRectF.right = cirX + radius
        mRectF.bottom = cirY + radius
        //在饼图中显示所占比例
        drawArc(mRectF, startAngle, sweepAngle, useCenter, paintArc)
}


fun Canvas.drawPathArc(
    paintArc: Paint,
    cirX: Float,
    cirY: Float,
    radius: Float,
    startAngle: Float,
    sweepAngle: Float,
    drawStyle: DrawStyle = DrawStyle.DEFAULT
) {
        val mRectF = RectF()
        mRectF.left = cirX - radius
        mRectF.top = cirY - radius
        mRectF.right = cirX + radius
        mRectF.bottom = cirY + radius
        //弧形
        val mPath= Path()
        mPath.addArc(mRectF, startAngle, sweepAngle)
        drawPath(mPath, paintArc)
        mRectF.setEmpty()
}



fun Canvas.rotate(x: Float, y: Float, degreesAngle: Float, drawFun:Canvas.()->Unit){
    if(degreesAngle == 0f)
        drawFun(this)
    else {
        rotate(degreesAngle, x, y)
        drawFun(this)
        rotate(-1 * degreesAngle, x, y)
    }
}

fun Canvas.clipRect( rect: Rectangle) = clipRect(rect.left, rect.top, rect.right, rect.bottom)


inline fun Canvas.saveLayer(rect: Rectangle, block: Canvas.() -> Unit){
    saveLayer(rect.left,rect.top,rect.right,rect.bottom)
    block()
    restore()
}

inline fun Canvas.inClip(
    rect: Rectangle,
    isSave:Boolean = false,
    block: Canvas.() -> Unit,
) {
    inClip(rect.left, rect.top, rect.right, rect.bottom,isSave, block)
}


/**
 * Clips the given [rect] in the receiver [Canvas], runs the [block], and releases the clip.
 *
 * @see [Canvas.clipRect]
 */
inline fun Canvas.inClip(
    rect: RectF,
    isSave:Boolean = false,
    block: Canvas.() -> Unit
) {
    inClip(rect.left, rect.top, rect.right, rect.bottom, isSave,block)
}

inline fun Canvas.inClip(
    path: Path,
    isSave:Boolean = false,
    pathPaint:Paint? =  Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color=Color.BLACK
        style=Paint.Style.STROKE
        isAntiAlias = true
        strokeWidth=1f
    },
    block: Canvas.() -> Unit
) {
    if(isSave){
        withSave {
            clipPath(path)
            block(this)
            if (pathPaint != null) {
                drawPath(path,pathPaint)
            }
        }
    }else{
        clipPath(path)
        block(this)
        if (pathPaint != null) {
            drawPath(path,pathPaint)
        }
    }
}

/**
 * Clips the given rectangle in the receiver [Canvas], runs the [block], and releases the clip.
 *
 * @see [Canvas.clipRect]
 */
 inline fun Canvas.inClip(
    left: Float,
    top: Float,
    right: Float,
    bottom: Float,
    isSave:Boolean = false,
    block: Canvas.() -> Unit,
) {
    if(isSave){
        withSave {
            clipRect(left, top, right, bottom)
            block(this)
        }
    }else{
        clipRect(left, top, right, bottom)
        block(this)
    }

}

/**
 * A convenience function for [Canvas.saveLayer].
 */
@Suppress("DEPRECATION")
fun Canvas.saveLayer(
    left: Float,
    top: Float,
    right: Float,
    bottom: Float,
): Int =
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        saveLayer(left, top, right, bottom, null)
    } else {
        saveLayer(left, top, right, bottom, null, Canvas.ALL_SAVE_FLAG)
    }

internal class Fill {

    /**
     * the type of fill
     */
    var type = FillType.EMPTY

    /**
     * the color that is used for filling
     */

    var color: Int? = null

    private var mFinalColor: Int? = null

    /**
     * the drawable to be used for filling
     */

    protected var mDrawable: Drawable? = null


    var gradientColors: IntArray? =null


    var gradientPositions: FloatArray? =null

    /**
     * transparency used for filling
     */
    private var mAlpha = 255

    constructor() {}
    constructor(color: Int) {
        type = FillType.COLOR
        this.color = color
        calculateFinalColor()
    }

    constructor(startColor: Int, endColor: Int) {
        type = FillType.LINEAR_GRADIENT
        gradientColors = intArrayOf(startColor, endColor)
    }

    constructor( gradientColors: IntArray) {
        type = FillType.LINEAR_GRADIENT
        this.gradientColors = gradientColors
    }

    constructor( gradientColors: IntArray, gradientPositions: FloatArray) {
        type = FillType.LINEAR_GRADIENT
        this.gradientColors = gradientColors
        this.gradientPositions = gradientPositions
    }

    constructor(drawable: Drawable) {
        type = FillType.DRAWABLE
        mDrawable = drawable
    }


    var alpha: Int
        get() = mAlpha
        set(alpha) {
            mAlpha = alpha
            calculateFinalColor()
        }

    private fun calculateFinalColor() {
        mFinalColor = if (color == null) {
            null
        } else {
            val alpha = floor((color!! shr 24) / 255.0 * (mAlpha / 255.0) * 255.0).toInt()
            alpha shl 24 or (color!! and 0xffffff)
        }
    }

    fun fillRect(c: Canvas, paint: Paint, rectF: RectF,gradientDirection: Direction = Direction.RIGHT){
        fillRect(c,paint,rectF.left,rectF.top,rectF.right,rectF.bottom, gradientDirection )
    }

    fun fillRect(
        c: Canvas, paint: Paint,
        left: Float, top: Float, right: Float, bottom: Float,
        gradientDirection: Direction
    ) {
        when (type) {
            FillType.EMPTY -> return
            FillType.COLOR -> {
                if (mFinalColor == null) return
                if (isClipPathSupported) {
                    val save = c.save()
                    c.clipRect(left, top, right, bottom)
                    c.drawColor(mFinalColor!!)
                    c.restoreToCount(save)
                } else {
                    // save
                    val previous = paint.style
                    val previousColor = paint.color

                    // set
                    paint.style = Paint.Style.FILL
                    paint.color = mFinalColor!!
                    c.drawRect(left, top, right, bottom, paint)

                    // restore
                    paint.color = previousColor
                    paint.style = previous
                }
            }
            FillType.LINEAR_GRADIENT -> {
                if (gradientColors == null) return
                val gradient = LinearGradient(
                    (if (gradientDirection == Direction.RIGHT) right else if (gradientDirection == Direction.LEFT) left else left),
                    (if (gradientDirection == Direction.UP) bottom else if (gradientDirection == Direction.DOWN) top else top),
                    (if (gradientDirection == Direction.RIGHT) left else if (gradientDirection == Direction.LEFT) right else left),
                    (if (gradientDirection == Direction.UP) top else if (gradientDirection == Direction.DOWN) bottom else top),
                    gradientColors!!,
                    gradientPositions,
                    Shader.TileMode.MIRROR
                )
                paint.shader = gradient
                c.drawRect(left, top, right, bottom, paint)
            }
            FillType.DRAWABLE -> {
                if (mDrawable == null) return
                mDrawable!!.setBounds(left.toInt(), top.toInt(), right.toInt(), bottom.toInt())
                mDrawable!!.draw(c)
            }
        }
    }

    fun fillPath(
        c: Canvas, path: Path, paint: Paint,
        clipRect: RectF?
    ) {
        when (type) {
            FillType.EMPTY -> return
            FillType.COLOR -> {
                if (mFinalColor == null) return
                if (isClipPathSupported) {
                    val save = c.save()
                    c.clipPath(path)
                    c.drawColor(mFinalColor!!)
                    c.restoreToCount(save)
                } else {
                    // save
                    val previous = paint.style
                    val previousColor = paint.color

                    // set
                    paint.style = Paint.Style.FILL
                    paint.color = mFinalColor!!
                    c.drawPath(path, paint)

                    // restore
                    paint.color = previousColor
                    paint.style = previous
                }
            }
            FillType.LINEAR_GRADIENT -> {
                if (gradientColors == null) return
                val gradient = LinearGradient(
                    0f,
                    0f,
                    c.width.toFloat(),
                    c.height.toFloat(),
                    gradientColors!!,
                    gradientPositions,
                    Shader.TileMode.MIRROR
                )
                paint.shader = gradient
                c.drawPath(path, paint)
            }
            FillType.DRAWABLE -> {
                if (mDrawable == null) return
                val save = c.save()
                c.clipPath(path)
                mDrawable!!.setBounds(
                    clipRect?.left?.toInt() ?: 0,
                    clipRect?.top?.toInt() ?: 0,
                    clipRect?.right?.toInt() ?: c.width,
                    clipRect?.bottom?.toInt() ?: c.height
                )
                mDrawable!!.draw(c)
                c.restoreToCount(save)
            }
        }
    }

   val isClipPathSupported: Boolean = true

}

fun Canvas.fill(rect: RectF,paint: Paint,color: Int){
    Fill(color).fillRect(this,paint,rect)
}

fun Canvas.fill(rect: RectF,paint: Paint,startColor: Int,endColor: Int,gradientDirection: Direction = Direction.RIGHT){
    Fill(startColor,endColor).fillRect(this,paint,rect,gradientDirection)
}

fun Canvas.fill(rect: RectF,paint: Paint,drawable: Drawable){
    Fill(drawable).fillRect(this,paint,rect)
}

fun Canvas.fill(path: Path,rect: RectF,paint: Paint,color: Int){
    Fill(color).fillPath(this,path,paint,rect)
}

fun Canvas.fill(path: Path,rect: RectF,paint: Paint,startColor: Int,endColor: Int,gradientDirection: Direction = Direction.RIGHT){
    Fill(startColor,endColor).fillPath(this,path,paint,rect)
}

fun Canvas.fill(path: Path,clipRect: RectF?,paint: Paint,drawable: Drawable){
    Fill(drawable).fillPath(this,path,paint,clipRect)
}